using System;
using System.Diagnostics;
using BepuUtilities.Memory;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace BepuUtilities.Collections
{
    /// <summary>
    /// 容器支持建立在非托管缓冲区之上的类似列表的行为。
    /// </summary>
    /// <remarks>
    /// 使用此类型时要非常小心。它在性能的祭坛上牺牲了很多;几个值得注意的问题包括：
    /// 它是一种值类型,复制它会在不加注意的情况下破坏东西,
    /// 它不能被有效地缺省构造,
    /// 它将内部结构暴露给用户修改,
    /// 它很少检查输入是否有错误,
    /// 枚举器不检查枚举中期修改,
    /// 它允许不安全的添加,如果用户不管理容量可能会中断,
    /// 它在抽象的存储器二进制大对象之上工作,该抽象的存储器二进制大对象在内部可能是可以被拉动的指针,
    /// 它不(也不能)检查所提供的内存是否返回到它来自的同一池。
    /// </remarks>
    /// <typeparam name="T">列表中元素的类型。</typeparam>
    public struct QuickList<T> where T : unmanaged
    {
        /// <summary>
        /// 包含列表元素的后备存储器。
        /// 从0到COUNT-1的索引保存实际数据。所有其他数据均未定义。
        /// </summary>
        public Buffer<T> Span;

        /// <summary>
        /// 列表中的元素数。
        /// </summary>
        public int Count;

        /// <summary>
        /// 获取对列表中给定索引处的元素的引用。
        /// </summary>
        /// <param name="index">从中获取元素的索引。</param>
        /// <return>列表中给定索引处的元素。</return>
        public ref T this[int index]
        {
            // TODO：在版本中检查内联
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            get
            {
                ValidateIndex(index);
                return ref Span[index];
            }
        }

        /// <summary>
        /// 获取指向列表中给定索引处的元素的指针。
        /// </summary>
        /// <param name="index">从中获取元素指针的索引。</param>
        /// <return>指向列表中给定索引处的元素的指针。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public unsafe T* GetPointer(int index)
        {
            ValidateIndex(index);
            return Span.GetPointer(index);
        }

        /// <summary>
        /// 创建新列表。
        /// </summary>
        /// <param name="initialSpan">开始用作后备内存的范围。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public QuickList(in Buffer<T> initialSpan)
        {
            Span = initialSpan;
            Count = 0;
        }

        /// <summary>
        /// 创建新列表。
        /// </summary>
        /// <param name="pool">要从中拉取跨区的池。</param>
        /// <param name="minumInitialCount">要从池中拉取的区域的最小大小。实际跨度可能更大。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public QuickList(int minimumInitialCount, IUnmanagedMemoryPool pool)
        {
            pool.TakeAtLeast(minimumInitialCount, out Span);
            Count = 0;
        }


        /// <summary>
        /// 将列表的后备内存范围换成新的范围。
        /// 如果新的跨度较小,列表的计数将被截断,额外的元素将被删除。
        /// 旧跨度不会被清除或返回到任何池;如果需要将其池化或清除,则用户必须处理它。
        /// </summary>
        /// <param name="newSpan">要使用的新范围。</param>
        /// <param name="oldSpan">用于元素的上一个范围。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Resize(ref Buffer<T> newSpan, out Buffer<T> oldSpan)
        {
            Validate();
            oldSpan = Span;
            Debug.Assert(oldSpan.Length != newSpan.Length, "Resizing without changing the size is pretty peculiar. Is something broken?");
            Span = newSpan;
            if (Count > Span.Length)
                Count = Span.Length;
            oldSpan.CopyTo(0, Span, 0, Count);

        }

        /// <summary>
        /// 根据给定大小调整列表的支持数组的大小。
        /// 任何不适合调整大小范围的元素都将被删除,并且计数将被截断。
        /// </summary>
        /// <param name="NewSize">新支持数组中所需的最小元素数。创建的跨度的实际容量可能超过此大小。</param>
        /// <param name="pool">要从中提取新跨度并将旧跨度返回到的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Resize(int newSize, IUnmanagedMemoryPool pool)
        {
            var targetSize = pool.GetCapacityForCount<T>(newSize);
            if (targetSize != Span.Length)
            {
                var oldList = this;
                pool.TakeAtLeast<T>(targetSize, out var newSpan);
                Resize(ref newSpan, out var oldSpan);
                oldList.Dispose(pool);
            }
        }

        /// <summary>
        /// 将与列表关联的资源返回到池。仍包含在列表中的任何托管引用都将被清除(某些非托管资源也可能被清除)。
        /// </summary>
        /// <param name="pool">用于元素跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Dispose(IUnmanagedMemoryPool pool)
        {
            pool.Return(ref Span);
        }

        /// <summary>
        /// 确保列表有足够的空间来容纳指定数量的元素。可用于初始化列表。
        /// </summary>
        /// <param name="count">要保存的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void EnsureCapacity(int count, IUnmanagedMemoryPool pool)
        {
            if (Span.Allocated)
            {
                if (count > Span.Length)
                {
                    Resize(count, pool);
                }
            }
            else
            {
                pool.TakeAtLeast(count, out Span);
            }
        }

        /// <summary>
        /// 将内部缓冲区压缩到列表中元素数量所需的最小大小。
        /// </summary>
        public void Compact(IUnmanagedMemoryPool pool)
        {
            Validate();
            var targetLength = pool.GetCapacityForCount<T>(Count);
            if (targetLength != Span.Length)
                Resize(targetLength, pool);
        }

        /// <summary>
        /// 将缓冲区的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in Buffer<T> span, int start, int count)
        {
            Validate();
            ValidateUnsafeAdd(count);
            SpanHelper.Copy(span, start, Span, Count, count);
            Count += count;
        }

        /// <summary>
        /// 将缓冲区的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in Buffer<T> span, int start, int count, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + count, pool);
            AddRangeUnsafely(span, start, count);
        }

        /// <summary>
        /// 将缓冲区的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in Buffer<T> span)
        {
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 将缓冲区的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in Buffer<T> span, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + span.Length, pool);
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in Span<T> span, int start, int count)
        {
            Validate();
            ValidateUnsafeAdd(count);
            SpanHelper.Copy(span, start, Span, Count, count);
            Count += count;
        }

        /// <summary>
        /// 将范围的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in Span<T> span, int start, int count, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + count, pool);
            AddRangeUnsafely(span, start, count);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in Span<T> span)
        {
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in Span<T> span, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + span.Length, pool);
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in ReadOnlySpan<T> span, int start, int count)
        {
            Validate();
            ValidateUnsafeAdd(count);
            SpanHelper.Copy(span, start, Span, Count, count);
            Count += count;
        }

        /// <summary>
        /// 将范围的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in ReadOnlySpan<T> span, int start, int count, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + count, pool);
            AddRangeUnsafely(span, start, count);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表,而不检查容量。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRangeUnsafely(in ReadOnlySpan<T> span)
        {
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 将范围的元素添加到快速列表。
        /// </summary>
        /// <param name="span">要添加的元素范围。</param>
        /// <param name="start">添加范围的起始索引。</param>
        /// <param name="count">添加区域中的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddRange(in ReadOnlySpan<T> span, IUnmanagedMemoryPool pool)
        {
            EnsureCapacity(Count + span.Length, pool);
            AddRangeUnsafely(span, 0, span.Length);
        }

        /// <summary>
        /// 在不检查容量的情况下在列表末尾追加空格,并返回对它的引用。
        /// </summary>
        /// <return>对已分配空间的引用。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ref T AllocateUnsafely()
        {
            ValidateUnsafeAdd();
            return ref Span[Count++];
        }


        /// <summary>
        /// 在不检查容量的情况下在列表末尾追加空格,并返回对列表开头的引用。
        /// </summary>
        /// <param name="count">要为其分配空间的元素数。</param>
        /// <return>对已分配空间开头的引用。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ref T AllocateUnsafely(int count)
        {
            var newCount = Count + count;
            Debug.Assert(newCount <= Span.Length, "Capacity must be large enough to hold the requested space.");
            ref var start = ref Span[Count];
            Count = newCount;
            return ref start;
        }


        /// <summary>
        /// 在列表末尾追加空格并返回对它的引用。
        /// </summary>
        /// <return>对已分配空间的引用。</return>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ref T Allocate(IUnmanagedMemoryPool pool)
        {
            if (Count == Span.Length)
                Resize(Count * 2, pool);
            return ref AllocateUnsafely();
        }

        /// <summary>
        /// 在列表末尾追加空格,并返回对列表开头的引用。
        /// </summary>
        /// <return>对已分配空间开头的引用。</return>
        /// <param name="count">要为其分配空间的元素数。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ref T Allocate(int count, IUnmanagedMemoryPool pool)
        {
            var newCount = Count + count;
            if (newCount > Span.Length)
                Resize(Math.Max(Count * 2, newCount), pool);
            ref var start = ref Span[Count];
            Count = newCount;
            return ref start;
        }

        /// <summary>
        /// 将元素添加到列表,而不对照容量检查计数。
        /// </summary>
        /// <param name="element">要添加的项目。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void AddUnsafely(in T element)
        {
            Validate();
            ValidateUnsafeAdd();
            AllocateUnsafely() = element;
        }

        /// <summary>
        /// 将元素添加到列表。
        /// </summary>
        /// <param name="element">要添加的项目。</param>
        /// <param name="pool">用于在需要时获取新跨度的池。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Add(in T element, IUnmanagedMemoryPool pool)
        {
            Validate();
            if (Count == Span.Length)
                Resize(Count * 2, pool);
            AddUnsafely(element);
        }

        /// <summary>
        /// 使用默认比较器(如果存在)获取列表中元素的索引。
        /// </summary>
        /// <param name="element">要查找的元素。</param>
        /// <return>列表中元素的索引(如果存在),否则为-1。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int IndexOf(T element)
        {
            Validate();
            return Span.IndexOf(ref element, 0, Count);
        }


        /// <summary>
        /// 使用默认比较器(如果存在)获取列表中元素的索引。
        /// </summary>
        /// <param name="element">要查找的元素。</param>
        /// <return>列表中元素的索引(如果存在),否则为-1。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int IndexOfRef(ref T element)
        {
            Validate();
            return Span.IndexOf(ref element, 0, Count);
        }

        /// <summary>
        /// 获取列表中与谓词匹配的第一个元素的索引(如果有)。
        /// </summary>
        /// <param name="谓词">要匹配的谓词。</param>
        /// <return>列表中第一个匹配元素的索引(如果存在),否则为-1。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public int IndexOf<TPredicate>(ref TPredicate predicate) where TPredicate : IPredicate<T>
        {
            Validate();
            return Span.IndexOf(ref predicate, 0, Count);
        }

        /// <summary>
        /// 从列表中删除元素。保留元素的顺序。
        /// </summary>
        /// <param name="element">要从列表中删除的元素。</param>
        /// <return>如果元素存在且已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Remove(ref T element)
        {
            Validate();
            var index = IndexOfRef(ref element);
            if (index >= 0)
            {
                RemoveAt(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从列表中删除元素。保留元素的顺序。
        /// </summary>
        /// <param name="element">要从列表中删除的元素。</param>
        /// <return>如果元素存在且已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Remove(T element)
        {
            return Remove(ref element);
        }

        /// <summary>
        /// 从列表中移除与谓词匹配的第一个元素。保留元素的顺序。
        /// </summary>
        /// <param name="谓词">用于测试元素的谓词。</param>
        /// <return>如果元素匹配并已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Remove<TPredicate>(ref TPredicate predicate) where TPredicate : IPredicate<T>
        {
            Validate();
            var index = Span.IndexOf(ref predicate, 0, Count);
            if (index >= 0)
            {
                RemoveAt(index);
                return true;
            }
            return false;
        }



        /// <summary>
        /// 从列表中删除元素。不保留元素的顺序。
        /// </summary>
        /// <param name="element">要从列表中删除的元素。</param>
        /// <return>如果元素存在且已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool FastRemoveRef(ref T element)
        {
            Validate();
            var index = IndexOf(element);
            if (index >= 0)
            {
                FastRemoveAt(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从列表中删除元素。比较使用该类型的默认比较器。不保留元素的顺序。
        /// </summary>
        /// <param name="element">要从列表中删除的元素。</param>
        /// <return>如果元素存在且已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool FastRemove(T element)
        {
            return FastRemoveRef(ref element);
        }

        /// <summary>
        /// 从列表中移除与谓词匹配的第一个元素,从低索引移动到高索引。不保留元素的顺序。
        /// </summary>
        /// <param name="谓词">用于测试元素的谓词。</param>
        /// <return>如果元素匹配并已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool FastRemove<TPredicate>(ref TPredicate predicate) where TPredicate : IPredicate<T>
        {
            Validate();
            var index = Span.IndexOf(ref predicate, 0, Count);
            if (index >= 0)
            {
                FastRemoveAt(index);
                return true;
            }
            return false;
        }

        /// <summary>
        /// 从列表中移除给定索引处的元素。保留元素的顺序。
        /// </summary>
        /// <param name="index">要从列表中删除的元素的索引。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void RemoveAt(int index)
        {
            Validate();
            ValidateIndex(index);
            --Count;
            if (index < Count)
            {
                // 从删除点往后复制所有内容,向后复制一个插槽。
                Span.CopyTo(index + 1, Span, index, Count - index);
            }
            // 清空之前的最后一个插槽。
            Span[Count] = default;
        }

        /// <summary>
        /// 从列表中移除给定索引处的元素。不保留元素的顺序。
        /// </summary>
        /// <param name="index">要从列表中删除的元素的索引。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void FastRemoveAt(int index)
        {
            Validate();
            ValidateIndex(index);
            --Count;
            if (index < Count)
            {
                // 将最后一个元素放入移除的插槽中。
                Span[index] = Span[Count];
            }
            // 清空之前的最后一个插槽。
            Span[Count] = default;
        }

        /// <summary>
        /// 移除并输出列表中的最后一个元素。假定为正计数。用户有责任保证其正确性。
        /// </summary>
        /// <param name="element">列表的最后一个元素。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Pop(out T element)
        {
            Validate();
            Debug.Assert(Count > 0, "It's up to the user to guarantee that the count is actually positive when using the unconditional pop.");
            Count--;
            element = Span[Count];
        }

        /// <summary>
        /// 移除并输出列表中的最后一个元素(如果存在)。
        /// </summary>
        /// <param name="element">列表的最后一个元素。</param>
        /// <return>如果元素存在且已删除,则为True,否则为False。</return>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool TryPop(out T element)
        {
            Validate();
            if (Count > 0)
            {
                Count--;
                element = Span[Count];
                return true;
            }
            element = default;
            return false;
        }

        /// <summary>
        /// 确定<See cref="T:System.Collections.Generic.ICollection`1"/>是否包含特定值。
        /// </summary>
        /// <退货>
        /// 如果在<See cref="T:System.Collections.Generic.ICollection`1"/>;否则为False中找到<paramref name="Element"/>,则为True。
        /// </return>
        /// 要在<请参阅cref="T:System.Collections.Generic.ICollection`1"/>.</param>中定位的对象
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Contains(T element)
        {
            return IndexOf(element) >= 0;
        }

        /// <summary>
        /// 确定集合是否包含特定值。
        /// </summary>
        /// <退货>
        /// 如果在集合中找到<paramref name="element"/>,则为true;否则为false。
        /// </return>
        /// <param name="element">要在集合中定位的对象。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool ContainsRef(ref T element)
        {
            return IndexOfRef(ref element) >= 0;
        }

        /// <summary>
        /// 确定集合是否包含与谓词匹配的元素。
        /// </summary>
        /// <退货>
        /// 如果存在与谓词匹配的元素,则为true,否则为false。
        /// </return>
        /// <param name="谓词">要针对列表中的元素进行测试的谓词。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Contains<TPredicate>(ref TPredicate predicate) where TPredicate : IPredicate<T>
        {
            return Span.IndexOf(ref predicate, 0, Count) >= 0;
        }


        /// <summary>
        /// 通过将计数设置为零并将支持数组中的所有相关索引显式设置为默认值来清除列表。
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void Clear()
        {
            Validate();
            Span.Clear(0, Count);
            Count = 0;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public unsafe static implicit operator Span<T>(in QuickList<T> list)
        {
            return new Span<T>(list.Span.Memory, list.Count);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public unsafe static implicit operator ReadOnlySpan<T>(in QuickList<T> list)
        {
            return new ReadOnlySpan<T>(list.Span.Memory, list.Count);
        }


        public Enumerator GetEnumerator()
        {
            return new Enumerator(ref Span, Count);
        }


        public struct Enumerator : IEnumerator<T>
        {
            private readonly Buffer<T> span;
            private readonly int count;
            private int index;

            public Enumerator(ref Buffer<T> span, int count)
            {
                this.span = span;
                this.count = count;
                index = -1;
            }

            public T Current
            {
                get { return span[index]; }
            }

            public void Dispose()
            {
            }

            object System.Collections.IEnumerator.Current
            {
                get { return Current; }
            }

            public bool MoveNext()
            {
                return ++index < count;
            }

            public void Reset()
            {
                index = -1;
            }
        }


        [Conditional("DEBUG")]
        void ValidateIndex(int index)
        {
            Debug.Assert(index >= 0 && index < Count, "Index must be nonnegative and less than the number of elements in the list.");
        }

        [Conditional("DEBUG")]
        private void Validate()
        {
            Debug.Assert(Span.Length > 0, "Any QuickList in use should have a nonzero length Span. Was this instance default constructed without further initialization?");
        }

        [Conditional("DEBUG")]
        void ValidateUnsafeAdd()
        {
            Debug.Assert(Count < Span.Length, "Unsafe adders can only be used if the capacity is guaranteed to hold the new size.");
        }
        [Conditional("DEBUG")]
        void ValidateUnsafeAdd(int elementsToAddCount)
        {
            Debug.Assert(Count + elementsToAddCount <= Span.Length, "Unsafe adders can only be used if the capacity is guaranteed to hold the new size.");
        }

    }
}
